// My includes
#include "Database.h"

Database::Database()
{
	//conn = new Connection(true);

	// MySQL
	mysql_init(&mMySQL);
}

Database::~Database()
{
	mysql_close(mConnection);
}

bool Database::connect()
{
	//if(conn.connect("projectx", "127.0.0.1", "root", "colombia", 3306))
	//{
	//	printf("MySQL DATABASE CONNECTION SUCCESFULL\n");
	//	return true;
	//}else{
	//	printf("MySQL DATABASE CONNECTION UNSUCCESFULL\n");
	//	return false;
	//}

	// MySQL
	mConnection = mysql_real_connect(&mMySQL, DB_HOST, DB_USER, DB_PASS, DB_DATABASE,3306,0,0);
	if(mConnection == NULL)
	{
		printf(mysql_error(&mMySQL));
		return false;
	}
	else
	{
		printf("MySQL DATABASE CONNECTION SUCCESFULL\n");
		return true;
	}
}

void Database::setServer(Server* svr)
{
	server = svr;
}

bool Database::checkAccount(RakString account, RakString password)
{
	RakString que = "select * from accounts where account = '";
	que += account;
	que += "' ";
	que += "and password = '";
	que += password;
	que += "'";
	printf("QUERY : %s\n", que.C_String());
	//Query query = conn.query(que.C_String());
	//if (StoreQueryResult res = query.store())
	//{
	//	if(res.num_rows()==1)
	//	{
	//		return true;
	//	} else return false;
	//} else return false;

	// MySQL
	mQueryState = mysql_query(mConnection, que.C_String());
	if (mQueryState !=0)
	{
		printf(mysql_error(mConnection));
		return false;
	}

	mResult = mysql_store_result(mConnection);
	if ( ( mRow = mysql_fetch_row(mResult) ) != NULL )
	{
		return true;
	} else return false;

}

void Database::retrieveCharacters(RakString account, Packet *packet)
{
	// Retrieve account id
	RakString que = "SELECT id FROM accounts WHERE account = '";
	que += account;
	que += "'";
	printf("QUERY : %s\n", que.C_String());
	//Query query = conn.query(que.C_String());
	//if (StoreQueryResult res = query.store())
	//{
	//	// Account id found, get all characters from account
	//	RakString accountId = res[0][0].c_str();
	//	sendCharacters(accountId, packet);
	//}

	// MySQL
	mQueryState = mysql_query(mConnection, que.C_String());
	if (mQueryState !=0)
	{
		printf(mysql_error(mConnection));
		return;
	}

	mResult = mysql_store_result(mConnection);
	if ( ( mRow = mysql_fetch_row(mResult) ) != NULL )
	{
		RakString accountId = mRow[0];
		sendCharacters(accountId, packet);
		return;
	}
}

void Database::sendCharacters(RakString account, Packet *packet)
{
	RakString que = "SELECT * FROM characters WHERE account = '";
	que += account;
	que += "'";
	printf("QUERY : %s\n", que.C_String());
	//Query query = conn.query(que.C_String());
	//if (StoreQueryResult res = query.store())
	//{
	//	if(res.num_rows()==0)
	//	{
	//		// Let the client know no characters where found
	//		MessageID typeId = MSG_NO_CHARACTERS;
	//		BitStream data;
	//		data.Write(typeId);
	//		data.Write(account);
	//		server->peer->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);
	//	}
	//	else
	//	{
	//		// Retrieve all the characters for the account and send to client
	//		int numChars = res.num_rows();
	//		RakString pName[5];
	//		int pLevel[5];
	//		int pClass[5];
	//		RakString pMesh[5];

	//		// Network stuff
	//		MessageID typeId = MSG_CHARACTER_LIST;
	//		BitStream data;
	//		data.Write(typeId);
	//		data.Write(numChars);
	//		data.Write(account);

	//		// Fill character array and add to BitStream
	//		for(int i = 0; i < numChars; i++)
	//		{
	//			pName[i] = res[i][2].c_str();
	//			pLevel[i] = res[i][3];
	//			pClass[i] = res[i][4];
	//			pMesh[i] = res[i][9].c_str();
	//			data.Write(pName[i]);
	//			data.Write(pLevel[i]);
	//			data.Write(pClass[i]);
	//			data.Write(pMesh[i]);
	//		}

	//		// Send character array to client
	//		server->peer->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);

	//		printf("SENDING CHARACTER DATA FOR ACCOUNT %s\n", account.C_String());
	//	}
	//}

	// MySQL
	mQueryState = mysql_query(mConnection, que.C_String());
	if (mQueryState !=0)
	{
		printf(mysql_error(mConnection));
		return;
	}

	mResult = mysql_store_result(mConnection);
	if ( ( mRow = mysql_fetch_row(mResult) ) != NULL )
	{
		// Retrieve all the characters for the account and send to client
		int numChars = mResult->row_count;
		RakString pName[5];
		int pLevel[5];
		int pClass[5];
		RakString pMesh[5];

		// Network stuff
		MessageID typeId = MSG_CHARACTER_LIST;
		BitStream data;
		data.Write(typeId);
		data.Write(numChars);
		data.Write(account);

		// Fill character array and add to BitStream
		for(int i = 0; i < numChars; i++)
		{
			// Get values
			pName[i] = (char*)mRow[2];

			// Convert char * to int
			std::istringstream plevel(mRow[3]);
			int Plevel;
			plevel >> Plevel;
			pLevel[i] = Plevel;

			// Convert char * to int
			std::istringstream pclass(mRow[4]);
			int Pclass;
			pclass >> Pclass;
			pClass[i] = Pclass;

			pMesh[i] = (char*)mRow[9];

			// Add to BitStream
			data.Write(pName[i]);
			data.Write(pLevel[i]);
			data.Write(pClass[i]);
			data.Write(pMesh[i]);

			// Get next row
			mRow = mysql_fetch_row(mResult);
		}

		// Send character array to client
		server->peer->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);

		printf("SENDING CHARACTER DATA FOR ACCOUNT %s\n", account.C_String());
		return;
	}
	else
	{
		// Let the client know no characters where found
		MessageID typeId = MSG_NO_CHARACTERS;
		BitStream data;
		data.Write(typeId);
		data.Write(account);
		server->peer->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);
		return;
	}
}

void Database::deleteCharacter(Packet *packet)
{
	BitStream dataStream((unsigned char*)packet->data, packet->length, false);

	MessageID typeId;
	RakString name;
	RakString accountId;
	dataStream.Read(typeId);
	dataStream.Read(name);
	dataStream.Read(accountId);

	// Retrieve account id
	RakString que = "DELETE FROM characters WHERE NAME = '";
	que += name;
	que += "';";
	printf("QUERY : %s\n", que.C_String());
	//Query query = conn.query(que.C_String());
	//StoreQueryResult res = query.store();

	// MySQL
	mQueryState = mysql_query(mConnection, que.C_String());
	if (mQueryState !=0)
	{
		printf(mysql_error(mConnection));
		return;
	}

	mResult = mysql_store_result(mConnection);
	mRow = mysql_fetch_row(mResult);

	// Send the new character data to the client
	sendCharacters(accountId, packet);

	return;
}

void Database::createCharacter(Packet *packet)
{
	// Declare variables stored in BitStream
	MessageID typeId;
	RakString account;
	int cGender;
	int cClass;
	RakString cName;
	RakString cMesh;

	// Retrieve data from BitStream
	BitStream dataStream((unsigned char*)packet->data, packet->length, false);
	dataStream.Read(typeId);
	dataStream.Read(account);
	dataStream.Read(cGender);
	dataStream.Read(cClass);
	dataStream.Read(cName);
	dataStream.Read(cMesh);

	//// Insert character into the database
	char temp1[100];
	char temp2[100];
	RakString que = "INSERT INTO characters (account, name, class, model, gender) VALUES (";
	que += account;
	que += ",'";
	que += cName;
	que += "',";
	que += itoa(cClass, temp1, 10);
	que += ",'";
	que += cMesh;
	que += "',";
	que += itoa(cGender, temp2, 10);
	que += ");";
	printf("QUERY : %s\n", que.C_String());
	//Query query = conn.query(que.C_String());
	//StoreQueryResult res = query.store();

	// MySQL
	mQueryState = mysql_query(mConnection, que.C_String());
	if (mQueryState !=0)
	{
		printf(mysql_error(mConnection));
		return;
	}

	mResult = mysql_store_result(mConnection);
	mRow = mysql_fetch_row(mResult);

	// Send the new character data to the client
	sendCharacters(account, packet);

	return;
}

// Get all data for a character and send to client
void Database::getCharacter(Packet *packet)
{
	// Get data from BitStream
	MessageID typeId;
	RakString charName;
	BitStream data((unsigned char*)packet->data, packet->length, false);
	data.Read(typeId);
	data.Read(charName);

	// Form query
	RakString que = "SELECT * FROM characters WHERE name = '";
	que += charName;
	que += "';";
	printf("QUERY : %s\n", que.C_String());
	//Query query = conn.query(que.C_String());
	//if (StoreQueryResult res = query.store())
	//{
	//	// Retrieve data for BitStream
	//	PlayerData pInfo;

	//	typeId = MSG_CHARACTER_DATA;
	//	pInfo.mIp = packet->systemAddress;
	//	pInfo.mId = res[0][0];
	//	pInfo.mAccount = res[0][1];
	//	pInfo.mName = res[0][2].c_str();
	//	pInfo.mLevel = res[0][3];
	//	pInfo.mClass = res[0][4];
	//	pInfo.mStartPosition.x = res[0][5];
	//	pInfo.mStartPosition.y = res[0][6];
	//	pInfo.mStartPosition.z = res[0][7];
	//	pInfo.mStartRotation = res[0][8];
	//	pInfo.mModel = res[0][9].c_str();
	//	pInfo.mGender = res[0][10];

	//	// Populate BitStream
	//	BitStream dataStream;
	//	dataStream.Write(typeId);
	//	dataStream.Write(pInfo.mId);
	//	dataStream.Write(pInfo.mAccount);
	//	dataStream.Write(pInfo.mName);
	//	dataStream.Write(pInfo.mLevel);
	//	dataStream.Write(pInfo.mClass);
	//	dataStream.Write(pInfo.mStartPosition.x);
	//	dataStream.Write(pInfo.mStartPosition.y);
	//	dataStream.Write(pInfo.mStartPosition.z);
	//	dataStream.Write(pInfo.mStartRotation);
	//	dataStream.Write(pInfo.mModel);
	//	dataStream.Write(pInfo.mGender);
	//	dataStream.Write(pInfo.mIp);

	//	// Send data to client
	//	server->peer->Send(&dataStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);

	//	// Add player to array and send to every other client
	//	server->addPlayer(pInfo);
	//}

	// MySQL
	mQueryState = mysql_query(mConnection, que.C_String());
	if (mQueryState !=0)
	{
		printf(mysql_error(mConnection));
		return;
	}

	mResult = mysql_store_result(mConnection);
	if ( ( mRow = mysql_fetch_row(mResult) ) != NULL )
	{
		// Retrieve data for BitStream
		PlayerData pInfo;

		typeId = MSG_CHARACTER_DATA;
		pInfo.mIp = packet->systemAddress;

		// Char * to int
		std::istringstream tempid(mRow[0]);
		int tid;
		tempid >> tid;
		pInfo.mId = tid;

		// Char * to int
		std::istringstream tempaccount(mRow[1]);
		int taccount;
		tempaccount >> taccount;
		pInfo.mAccount = taccount;

		pInfo.mName = (char*)mRow[2];

		// Char * to int
		std::istringstream templevel(mRow[3]);
		int tlevel;
		templevel >> tlevel;
		pInfo.mLevel = tlevel;

		// Char * to int
		std::istringstream tempclass(mRow[4]);
		int tclass;
		tempclass >> tclass;
		pInfo.mClass = tclass;

		// Convert char * to float
		std::istringstream posx(mRow[5]);
		float posX;
		posx >> posX;
		pInfo.mStartPosition.x = posX;

		// Convert char * to float
		std::istringstream posy(mRow[6]);
		float posY;
		posy >> posY;
		pInfo.mStartPosition.y = posY;

		// Convert char * to float
		std::istringstream posz(mRow[7]);
		float posZ;
		posz >> posZ;
		pInfo.mStartPosition.z = posZ;

		// Char * to int
		std::istringstream tempstartrot(mRow[8]);
		int tstartrot;
		tempstartrot >> tstartrot;
		pInfo.mStartRotation = tstartrot;

		pInfo.mModel = (char *)mRow[9];

		// Char * to int
		std::istringstream tempgender(mRow[10]);
		int tgender;
		tempgender >> tgender;
		pInfo.mGender = tgender;

		// Populate BitStream
		BitStream dataStream;
		dataStream.Write(typeId);
		dataStream.Write(pInfo.mId);
		dataStream.Write(pInfo.mAccount);
		dataStream.Write(pInfo.mName);
		dataStream.Write(pInfo.mLevel);
		dataStream.Write(pInfo.mClass);
		dataStream.Write(pInfo.mStartPosition.x);
		dataStream.Write(pInfo.mStartPosition.y);
		dataStream.Write(pInfo.mStartPosition.z);
		dataStream.Write(pInfo.mStartRotation);
		dataStream.Write(pInfo.mModel);
		dataStream.Write(pInfo.mGender);
		dataStream.Write(pInfo.mIp);

		// Send data to client
		server->peer->Send(&dataStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);

		// Add player to array and send to every other client
		server->addPlayer(pInfo);

		return;
	}
}